package com.firexxx.vp.infrastructure.query.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.firexxx.common.domain.query.CacheConsistencyInterface;
import com.firexxx.common.utils.JacksonConverter;
import com.firexxx.vp.adapter.Constants;
import com.firexxx.vp.adapter.scheduled.CacheSynchronizationManager;
import com.firexxx.vp.domain.stb.*;
import com.firexxx.vp.domain.stb.query.StbQueryInterface;
import com.firexxx.vp.domain.vp.fuse.FuseVoicePrintEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.event.TransactionalEventListener;

import java.io.IOException;
import java.util.List;

/**
 * @description: TODO
 * @throws:
 * @author: zhuangzhang2
 * @date: 2019/12/25 17:22
 */
@Slf4j
public class StbRedisCache implements StbQueryInterface, CacheConsistencyInterface {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private CacheSynchronizationManager cacheSynchronizationManager;

    @Autowired
    private StbRepository stbRepository;

    @Override
    public StbEntity getOneByStbKey(StbKey stbKey) throws IOException {
        String result = stringRedisTemplate.opsForValue().get(Constants.APP_MAGIC + ":"
                + stbKey.getChannelId() + ":"
                + stbKey.getUniqueKey());
        if (result != null) {
            return JacksonConverter.toObject(result, StbEntity.class);
        }

        return null;
    }

//    @Async
//    @TransactionalEventListener
//    public void test(TestEvent testEvent) {
//        int a = 1;
//        a = 2;
//    }

    @Async
    @TransactionalEventListener
    public void save(StbCreatedEvent event) throws JsonProcessingException {
        StbEntity stbEntity = event.getSource();

        log.info("开始保存stb:{}到缓存", stbEntity.getStbKey());

        stringRedisTemplate.opsForValue().set(Constants.APP_MAGIC + ":"
                + stbEntity.getStbKey().getChannelId() + ":"
                + stbEntity.getStbKey().getUniqueKey(),
                JacksonConverter.toJson(stbEntity));

        log.info("保存stb:{}到缓存成功", stbEntity.getStbKey());
    }

    //TODO 考虑管道操作
    @Async
    @TransactionalEventListener
    public void save(StbRegisterFinishedEvent event) throws JsonProcessingException {
        log.info("开始保存stb:{}到缓存", event.getStbEntity().getStbKey());

//        log.error("------ready to redis {}:{}", event.getStbEntity().getUserGroupId(), event.getStbEntity().getVersion());

        stringRedisTemplate.opsForValue().set(Constants.APP_MAGIC + ":"
                + event.getStbEntity().getStbKey().getChannelId() + ":"
                + event.getStbEntity().getStbKey().getUniqueKey(), JacksonConverter.toJson(event.getStbEntity()));

        for (FuseVoicePrintEntity item : event.getNewFuseVoicePrintList()) {
            stringRedisTemplate.opsForValue().set(Constants.APP_MAGIC + ":"
                    + item.getVpModel().getVpId(),
                    JacksonConverter.toJson(item.getVpModel()));

            log.info("保存vpId:{}到缓存成功", item.getVpModel().getVpId());
        }
    }

    @Override
    public void register() {
        cacheSynchronizationManager.getCacheBeanList().add(this);
    }

    @Override
    public void consistency() {
        List<StbEntity> stbEntityList = stbRepository.findAll();

        for (StbEntity stbEntity : stbEntityList) {
            try {
                String result = stringRedisTemplate.opsForValue().get(Constants.APP_MAGIC + ":"
                        + stbEntity.getStbKey().getChannelId() + ":"
                        + stbEntity.getStbKey().getUniqueKey());

                StbEntity redisStbEntity = JacksonConverter.toObject(result, StbEntity.class);
                if (stbEntity.getVersion().intValue() != redisStbEntity.getVersion().intValue()) {
                    stringRedisTemplate.opsForValue().set(Constants.APP_MAGIC + ":"
                                    + stbEntity.getStbKey().getChannelId() + ":"
                                    + stbEntity.getStbKey().getUniqueKey(),
                            JacksonConverter.toJson(stbEntity));

                    log.info("重新同步缓存version不一致的stb:{}", stbEntity.getStbKey());
                }
            } catch (Exception e) {
                log.error("stb key {} error : {}", stbEntity.getStbKey().getUniqueKey(), e);
            }
        }
    }
}